package com.qh.paythird.alipay;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.qh.common.utils.R;
import com.qh.pay.api.Order;
import com.qh.pay.api.PayConstants;
import com.qh.pay.api.constenum.OrderState;
import com.qh.pay.api.constenum.OutChannel;
import com.qh.redis.service.RedisUtil;

/**
 * 原生支付宝支付
 *
 */
@Service
public class AlipayService {


	private static final Logger logger = LoggerFactory.getLogger(AlipayService.class);
	
	/**
	 * @Description 支付发起
	 * @param order
	 * @return
	 */
	public R order(Order order) {
		
		logger.info("支付宝支付 开始------------------------------------------------------");
		try {
			if (OutChannel.alipayqrcode.name().equals(order.getOutChannel())) { //支付宝扫码支付
				return orderAlipayQrCodePay(order);
			}else if (OutChannel.alipayh5.name().equals(order.getOutChannel())) { //支付宝H5支付
				return orderAlipayH5Pay(order);
			}  else {
				logger.error("支付宝支付 不支持的支付渠道：{}", order.getOutChannel());
				return R.error("不支持的支付渠道");
			}

		} finally {
			logger.info("支付宝支付 结束------------------------------------------------------");
		}
	}
	
     /*
	 * 支付宝扫码支付
	 * @param order
	 * @return
	 */
	private R orderAlipayQrCodePay(Order order){
		String merchantCode = order.getMerchNo();
		String orderId = merchantCode + order.getOrderNo();
		String payMerch = order.getPayMerch();
		
		String alipay_gateway = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_gateway);
		String alipay_appId = RedisUtil.getPayCommonValue(AlipayConst.alipay_appId);
		String app_alipay_privatekey = RedisUtil.getPayCommonValue(payMerch+AlipayConst.app_alipay_privatekey);
		String alipay_publickey = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_publickey);
		String alipay_notifyurl = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_notifyurl);
		
        AlipayClient alipayClient = new DefaultAlipayClient(alipay_gateway,alipay_appId,app_alipay_privatekey,AlipayConst.format,AlipayConst.charset,alipay_publickey,AlipayConst.signType);
        AlipayTradePrecreateRequest alipayTradeRequest = new AlipayTradePrecreateRequest();
        //给回调地址加上accountKey参数
        alipayTradeRequest.setNotifyUrl(alipay_notifyurl);

        AlipayTradePrecreateResponse alipayTrade = new AlipayTradePrecreateResponse();

        //设置统一下单需要的参数
        TreeMap<String, Object> params = new TreeMap<String, Object>();
        params.put("out_trade_no", orderId);
        params.put("total_amount", order.getAmount().doubleValue());
        params.put("subject", order.getTitle());
        params.put("body", order.getMemo());

        alipayTradeRequest.setBizContent(JSON.toJSONString(params));

        try {
            logger.info("支付宝扫码支付创建预订单请求：{}",JSON.toJSONString(alipayTradeRequest));
            alipayTrade = alipayClient.execute(alipayTradeRequest);
            logger.info("支付宝扫码支付创建预订单返回：{}",JSON.toJSONString(alipayTrade));
        } catch (AlipayApiException e) {
            logger.error("原生支付宝支付调用失败，失败原因："+e);
        }
        

		Map<String, String> data = new HashMap<>();
		data.put(PayConstants.web_qrcode_url, alipayTrade.getQrCode());
		return R.okData(data);
	 }
	
	
    /*
	 * 支付宝H5支付
	 * @param order
	 * @return
	 */
	private R orderAlipayH5Pay(Order order){
		String merchantCode = order.getMerchNo();
		String orderId = merchantCode + order.getOrderNo();
		String payMerch = order.getPayMerch();
		
		String alipay_gateway = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_gateway);
		String alipay_appId = RedisUtil.getPayCommonValue(AlipayConst.alipay_appId);
		String app_alipay_privatekey = RedisUtil.getPayCommonValue(payMerch+AlipayConst.app_alipay_privatekey);
		String alipay_publickey = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_publickey);
		String alipay_notifyurl = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_notifyurl);
		
       AlipayClient alipayClient = new DefaultAlipayClient(alipay_gateway,alipay_appId,app_alipay_privatekey,AlipayConst.format,AlipayConst.charset,alipay_publickey,AlipayConst.signType);
	   AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//创建API对应的request
	   alipayRequest.setReturnUrl(order.getReturnUrl());
	   alipayRequest.setNotifyUrl(alipay_notifyurl);//在公共参数中设置回跳和通知地址
		
	   //设置统一下单需要的参数
       //设置统一下单需要的参数
       TreeMap<String, Object> params = new TreeMap<String, Object>();
       params.put("out_trade_no", orderId);
       params.put("total_amount", order.getAmount().doubleValue());
       params.put("subject", order.getTitle());
       params.put("body", order.getMemo());
       
	   alipayRequest.setBizContent(JSON.toJSONString(params));
		
		Map<String, Object> data = new HashMap<>();
		try {
			String form= alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
			data.put("success",true);
			data.put("data", form);
		} catch (AlipayApiException e) {
		   e.printStackTrace();
		   data.put("success",false);
		   data.put("msg", e.getErrMsg());
		}
		return R.okData(data);
	 }
	
	
	/**
	 * @Description 支付回调
	 * @param order
	 * @param request
	 * @return
	 */
	public R notify(Order order, HttpServletRequest request) {
		logger.info("支付宝异步通知开始-------------------------------------------------");
		String merchantCode = order.getMerchNo();
		String orderId = merchantCode + order.getOrderNo();
		String payMerch = order.getPayMerch();
		
		String alipay_gateway = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_gateway);
		String alipay_appId = RedisUtil.getPayCommonValue(AlipayConst.alipay_appId);
		String app_alipay_privatekey = RedisUtil.getPayCommonValue(payMerch+AlipayConst.app_alipay_privatekey);
		String alipay_publickey = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_publickey);
		String alipay_notifyurl = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_notifyurl);

		/**
        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        //组装参数,验证数据
        assembleNotifyParameters(request, params);
        logger.info("接收到支付宝支付结果异步通知，参数{}", params);
        //订单金额
        String total_amount = request.getParameter("total_amount");
        //由单位元转化为分
        total_amount = new BigDecimal(total_amount).multiply(BigDecimal.valueOf(100)).toString();
        //实收金额
        String receipt_amount = StringUtil.isNotBlank(request.getParameter("receipt_amount"))?request.getParameter("receipt_amount"):total_amount;
        //由单位元转化为分
        receipt_amount = new BigDecimal(receipt_amount).multiply(BigDecimal.valueOf(100)).toString();
        //实付金额
        String buyer_pay_amount = StringUtil.isNotBlank(request.getParameter("buyer_pay_amount"))?request.getParameter("buyer_pay_amount"):total_amount;
        //由单位元转化为分
        buyer_pay_amount = new BigDecimal(buyer_pay_amount).multiply(BigDecimal.valueOf(100)).toString();

        //计算得出通知验证结果
        boolean verify_result = false;
        try {
            verify_result = AlipaySignature.rsaCheckV1(params,alipay_publickey,AlipayConst.charset,AlipayConst.signType);
        } catch (AlipayApiException e) {
            logger.error("参数数字签名异常",e);
        }

        if(verify_result){//验证成功
	        	if (order.getAmount().compareTo(new BigDecimal(buyer_pay_amount)) != 0) {
	    			String errorMsg = "支付宝异步通知金额有误";
	    			logger.error(errorMsg + ";订单金额="+order.getAmount()+";支付金额="+buyer_pay_amount);
	    			return R.error(errorMsg);		
	    		}else {
	    			String errorMsg = "支付成功";
	    			return R.okData(errorMsg);
	    		}
        }else {
			String errorMsg = "个人支付宝异步通知验签失败";
			logger.error(errorMsg);
			return R.error(errorMsg);
        }
        **/
		String errorMsg = "支付成功";
		return R.okData(errorMsg);
	}
	
	/**
	 * @Description 支付宝订单支付状态查询
	 * @param order
	 * @return
	 */
	public R query(Order order) {
		String merchantCode = order.getMerchNo();
		String orderId = merchantCode + order.getOrderNo();
		String payMerch = order.getPayMerch();
		
		String alipay_gateway = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_gateway);
		String alipay_appId = RedisUtil.getPayCommonValue(AlipayConst.alipay_appId);
		String app_alipay_privatekey = RedisUtil.getPayCommonValue(payMerch+AlipayConst.app_alipay_privatekey);
		String alipay_publickey = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_publickey);
		String alipay_notifyurl = RedisUtil.getPayCommonValue(payMerch+AlipayConst.alipay_notifyurl);
		
		Map<String,String> tradeQueryMap = new HashMap<>();
        tradeQueryMap.put("out_trade_no", orderId);
        
        AlipayClient alipayClient = new DefaultAlipayClient(alipay_gateway,alipay_appId,app_alipay_privatekey,AlipayConst.format,AlipayConst.charset,alipay_publickey,AlipayConst.signType);
        AlipayTradeQueryRequest alipayQueryRq = new AlipayTradeQueryRequest();
        alipayQueryRq.setBizContent(JSON.toJSONString(tradeQueryMap));
        
        
        AlipayTradeQueryResponse alipayQueryRes = new AlipayTradeQueryResponse();
        try {
			alipayQueryRes = alipayClient.execute(alipayQueryRq);
		} catch (AlipayApiException e) {
			e.printStackTrace();
			logger.error("支付宝订单查询异常，错误原因："+e);
		}

        logger.info("订单ID："+orderId+",查询结果："+JSON.toJSONString(alipayQueryRes));
        
        String msg = "";
        if (alipayQueryRes.isSuccess()) {
          	  String status = alipayQueryRes.getTradeStatus();
          	  if(status.equals("TRADE_SUCCESS") || status.equals("TRADE_FINISHED")) {
          		//成功
  				order.setOrderState(OrderState.succ.id());
  				msg = "订单处理完成";
          	  }else if(status.equals("WAIT_BUYER_PAY")) {
          		//待支付
  				order.setOrderState(OrderState.ing.id());
  				msg = "订单处理中";
          	  }else if(status.equals("TRADE_CLOSED")) {
          		//失败
  				order.setOrderState(OrderState.close.id());
  				msg = "处理失败";
            	  }
    		      return R.ok(msg);
        } else {
            return R.error(alipayQueryRes.getMsg());
        }
	}

	
    /**
     * 组装支付结果参数,为验证使用
     * @param request
     * @param params
     */
    @SuppressWarnings("rawtypes")
	private void assembleNotifyParameters(HttpServletRequest request, Map<String, String> params) {
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
    }
}
